package com.csair.platform.cit.service.core.aop;


import java.lang.reflect.Method;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Profile;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.csair.invoice.common.base.util.StringUtil;
import com.csair.invoice.common.base.vo.JsonResult;
import com.csair.platform.cit.service.core.CheckAnyPermission;
import com.csair.platform.cit.service.feignclient.usercenter.UserFeignClient;
import com.csair.platform.usercenter.facade.exception.UserCenterBizException;
import com.csair.platform.usercenter.facade.model.user.UserVo;


@Component
@Aspect
@Profile({"test", "prod"})
public class ActionAopAspect {
	
    // 日志信息
 	private static Logger logger = LoggerFactory.getLogger(ActionAopAspect.class);
 	
 	@Autowired
 	private UserFeignClient userFeignClient;
 	
    @Pointcut("@annotation(com.csair.platform.cit.service.core.CheckAnyPermission)")
    private void controllerAspect(){
    	
    }
    
    
    /**
     * 方法执行
     * @param pjp
     * @return
     * @throws Throwable
    */
    @Around(value="controllerAspect()")
    public Object before(ProceedingJoinPoint pjp) throws Throwable{
    	// 拦截的实体类，就是当前正在执行的controller
        Object target = pjp.getTarget();
        // 拦截的方法名称。当前正在执行的方法
        String methodName = pjp.getSignature().getName();
        HttpServletRequest req = this.getRequest();
        String token = StringUtil.trim(req.getHeader("token"));
        //1. 调用户中心获取用户账号
  		UserVo userVo = null;
  		JsonResult<UserVo> j =  userFeignClient.getUserFromCache(token);
  		if(j.isSuccess()) {
  			userVo = j.getData().get(0);
  		}
  		String account = "未知用户";
  		if(userVo != null) {
  			account = userVo.getAccount();
  		}
        logger.info(account +", 开始调用"+ target.getClass().getSimpleName() +"方法名:"+ methodName + "<<--请求路径：" +req.getRequestURI());
        // 拦截的放参数类型
        Signature sig = pjp.getSignature();
        if (!(sig instanceof MethodSignature)) {
            throw new IllegalArgumentException("该注解只能用于方法");
        }
        MethodSignature msig = (MethodSignature) sig;
        Class[] parameterTypes = msig.getMethod().getParameterTypes();
        Method method = null;
        try {
            method = target.getClass().getMethod(methodName, parameterTypes);
        } catch (NoSuchMethodException e1) {
            e1.printStackTrace();
        } catch (SecurityException e1) {
            e1.printStackTrace();
        }
        
        Object object = null;
        Object[] args = pjp.getArgs();
        boolean hasPermission = hasPermission(req, method, userVo);
        if(!hasPermission) {
        	throw UserCenterBizException.ACCESS_DENIED;
        } else {
        	object = pjp.proceed(args);
        }
        return object;
    } 
    
    
    /** 
     * 获取参数request 
     * @param point 
     * @return 
     */  
    private HttpServletRequest getRequest() {  
    	ServletRequestAttributes ra = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
    	HttpServletRequest req = ra.getRequest();
        return req;  
    }
    
    private boolean hasPermission(HttpServletRequest req, Method method, UserVo userVo){
    	
		//action方法是否有注解
		CheckAnyPermission permissionAnyCheck = AnnotationUtils.findAnnotation(method, CheckAnyPermission.class);
		
		//不存在注解，有权限访问
		if(permissionAnyCheck == null) {
			return true; 
		}
		//请求没带token， 无权限访问
		String token = req.getHeader("token");
		if(StringUtil.isEmpty(token)) {
			return false; 
		}
		//注解上没东西，有权限访问
		String[] values = permissionAnyCheck.values();
		if(values == null || values.length ==0 ) {
			return true;
		}
		//boolean hasPermission = userPermissionFeignClient.checkAnyPermission(token, permissionAnyCheck.values());

		//resourceCodes = 注解上的配置
		Boolean hasPermission = true;
		Set<String> cprivilege = userVo.getPermissionCodes();
		for(String permissionCode : values){
			if (!cprivilege.contains(permissionCode)){
				hasPermission = false;
				break;
			}
		}
		return hasPermission;
	}
}
